#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "WTSBaseDataMgr.h"
#include "WTSContractInfo.hpp"
#include "WTSSessionInfo.hpp"
#include <fstream>
#include <filesystem>
#include <thread>
#include <chrono>

/*!
 * \brief WTSBaseDataMgr基础数据管理器测试套件
 * 
 * \details 测试WTSBaseDataMgr类的核心功能，包括：
 *          - 合约信息管理
 *          - 品种信息管理
 *          - 交易时段管理
 *          - 交易所信息管理
 *          - 配置文件加载和解析
 *          - 数据查询和检索
 *          - 内存管理和资源清理
 *          - 多线程安全性
 *          - 错误处理和边界条件
 */
class WTSBaseDataMgrTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 创建测试目录
        test_dir = "test_base_data";
        std::filesystem::create_directories(test_dir);
        
        // 创建基础数据管理器
        base_data_mgr = new WTSBaseDataMgr();
        
        // 创建测试配置文件
        createTestCommodityConfig();
        createTestContractConfig();
        createTestSessionConfig();
        createTestExchangeConfig();
    }
    
    void TearDown() override {
        // 清理资源
        if (base_data_mgr) {
            delete base_data_mgr;
            base_data_mgr = nullptr;
        }
        
        // 清理测试文件
        std::filesystem::remove_all(test_dir);
    }
    
    /*!
     * \brief 创建测试用的品种配置文件
     */
    void createTestCommodityConfig() {
        std::ofstream file(test_dir + "/commodities.json");
        file << R"({
    "SHFE": {
        "au": {
            "name": "黄金",
            "pricetick": 0.05,
            "volscale": 1000,
            "category": 0,
            "covermode": 0,
            "pricemode": 0,
            "trademode": 2,
            "lotstick": 1,
            "minlots": 1,
            "session": "TRADING"
        },
        "ag": {
            "name": "白银",
            "pricetick": 1,
            "volscale": 15,
            "category": 0,
            "covermode": 0,
            "pricemode": 0,
            "trademode": 2,
            "lotstick": 1,
            "minlots": 1,
            "session": "TRADING"
        }
    },
    "DCE": {
        "m": {
            "name": "豆粕",
            "pricetick": 1,
            "volscale": 10,
            "category": 0,
            "covermode": 1,
            "pricemode": 0,
            "trademode": 2,
            "lotstick": 1,
            "minlots": 1,
            "session": "TRADING"
        }
    }
})";
        file.close();
    }
    
    /*!
     * \brief 创建测试用的合约配置文件
     */
    void createTestContractConfig() {
        std::ofstream file(test_dir + "/contracts.json");
        file << R"({
    "SHFE": {
        "au2412": {
            "name": "黄金2412",
            "code": "au2412",
            "exchg": "SHFE",
            "product": "au",
            "maxlimitqty": 500,
            "maxmarketqty": 100
        },
        "au2501": {
            "name": "黄金2501",
            "code": "au2501",
            "exchg": "SHFE",
            "product": "au",
            "maxlimitqty": 500,
            "maxmarketqty": 100
        },
        "ag2412": {
            "name": "白银2412",
            "code": "ag2412",
            "exchg": "SHFE",
            "product": "ag",
            "maxlimitqty": 1000,
            "maxmarketqty": 200
        }
    },
    "DCE": {
        "m2501": {
            "name": "豆粕2501",
            "code": "m2501",
            "exchg": "DCE",
            "product": "m",
            "maxlimitqty": 1000,
            "maxmarketqty": 200
        }
    }
})";
        file.close();
    }
    
    /*!
     * \brief 创建测试用的交易时段配置文件
     */
    void createTestSessionConfig() {
        std::ofstream file(test_dir + "/sessions.json");
        file << R"({
    "TRADING": {
        "name": "交易时段",
        "offset": 480,
        "sections": [
            {
                "from": 900,
                "to": 1015
            },
            {
                "from": 1030,
                "to": 1130
            },
            {
                "from": 1330,
                "to": 1500
            },
            {
                "from": 2100,
                "to": 230
            }
        ]
    },
    "NIGHT": {
        "name": "夜盘时段",
        "offset": 480,
        "sections": [
            {
                "from": 2100,
                "to": 230
            }
        ]
    }
})";
        file.close();
    }
    
    /*!
     * \brief 创建测试用的交易所配置文件
     */
    void createTestExchangeConfig() {
        std::ofstream file(test_dir + "/exchanges.json");
        file << R"({
    "SHFE": {
        "name": "上海期货交易所",
        "session": "TRADING"
    },
    "DCE": {
        "name": "大连商品交易所",
        "session": "TRADING"
    },
    "CZCE": {
        "name": "郑州商品交易所",
        "session": "TRADING"
    }
})";
        file.close();
    }
    
    /*!
     * \brief 创建空的配置文件用于测试
     */
    void createEmptyConfig(const std::string& filename) {
        std::ofstream file(test_dir + "/" + filename);
        file << "{}";
        file.close();
    }
    
    /*!
     * \brief 创建无效的配置文件用于测试
     */
    void createInvalidConfig(const std::string& filename) {
        std::ofstream file(test_dir + "/" + filename);
        file << "{ invalid json content";
        file.close();
    }

protected:
    std::string test_dir;
    WTSBaseDataMgr* base_data_mgr;
};

// ========== 基础功能测试 ==========

/*!
 * \brief 测试WTSBaseDataMgr基本初始化
 */
TEST_F(WTSBaseDataMgrTest, TestBasicInitialization) {
    ASSERT_NE(base_data_mgr, nullptr);
    
    // 测试初始状态
    EXPECT_EQ(base_data_mgr->getContract("au2412", "SHFE"), nullptr);
    EXPECT_EQ(base_data_mgr->getCommodity("SHFE", "au"), nullptr);
    EXPECT_EQ(base_data_mgr->getSession("TRADING"), nullptr);
}

/*!
 * \brief 测试品种配置文件加载
 */
TEST_F(WTSBaseDataMgrTest, TestLoadCommodityConfig) {
    // 加载品种配置文件
    bool result = base_data_mgr->loadCommodities((test_dir + "/commodities.json").c_str(), false);
    EXPECT_TRUE(result);
    
    // 验证SHFE交易所的品种
    WTSCommodityInfo* au_info = base_data_mgr->getCommodity("SHFE", "au");
    ASSERT_NE(au_info, nullptr);
    EXPECT_STREQ(au_info->getName(), "黄金");
    EXPECT_DOUBLE_EQ(au_info->getPriceTick(), 0.05);
    EXPECT_EQ(au_info->getVolScale(), 1000);
    
    WTSCommodityInfo* ag_info = base_data_mgr->getCommodity("SHFE", "ag");
    ASSERT_NE(ag_info, nullptr);
    EXPECT_STREQ(ag_info->getName(), "白银");
    EXPECT_DOUBLE_EQ(ag_info->getPriceTick(), 1.0);
    EXPECT_EQ(ag_info->getVolScale(), 15);
    
    // 验证DCE交易所的品种
    WTSCommodityInfo* m_info = base_data_mgr->getCommodity("DCE", "m");
    ASSERT_NE(m_info, nullptr);
    EXPECT_STREQ(m_info->getName(), "豆粕");
    EXPECT_DOUBLE_EQ(m_info->getPriceTick(), 1.0);
    EXPECT_EQ(m_info->getVolScale(), 10);
}

/*!
 * \brief 测试合约配置文件加载
 */
TEST_F(WTSBaseDataMgrTest, TestLoadContractConfig) {
    // 先加载品种配置
    ASSERT_TRUE(base_data_mgr->loadCommodities((test_dir + "/commodities.json").c_str(), false));
    
    // 加载合约配置文件
    bool result = base_data_mgr->loadContracts((test_dir + "/contracts.json").c_str(), false);
    EXPECT_TRUE(result);
    
    // 验证SHFE交易所的合约
    WTSContractInfo* au2412 = base_data_mgr->getContract("au2412", "SHFE");
    ASSERT_NE(au2412, nullptr);
    EXPECT_STREQ(au2412->getCode(), "au2412");
    EXPECT_STREQ(au2412->getName(), "黄金2412");
    EXPECT_STREQ(au2412->getProduct(), "au");
    EXPECT_EQ(au2412->getMaxLmtVol(), 500);
    EXPECT_EQ(au2412->getMaxMktVol(), 100);
    
    WTSContractInfo* au2501 = base_data_mgr->getContract("au2501", "SHFE");
    ASSERT_NE(au2501, nullptr);
    EXPECT_STREQ(au2501->getCode(), "au2501");
    EXPECT_STREQ(au2501->getName(), "黄金2501");
    
    WTSContractInfo* ag2412 = base_data_mgr->getContract("ag2412", "SHFE");
    ASSERT_NE(ag2412, nullptr);
    EXPECT_STREQ(ag2412->getCode(), "ag2412");
    EXPECT_STREQ(ag2412->getProduct(), "ag");
    
    // 验证DCE交易所的合约
    WTSContractInfo* m2501 = base_data_mgr->getContract("m2501", "DCE");
    ASSERT_NE(m2501, nullptr);
    EXPECT_STREQ(m2501->getCode(), "m2501");
    EXPECT_STREQ(m2501->getProduct(), "m");
}

/*!
 * \brief 测试交易时段配置文件加载
 */
TEST_F(WTSBaseDataMgrTest, TestLoadSessionConfig) {
    // 加载交易时段配置文件
    bool result = base_data_mgr->loadSessions((test_dir + "/sessions.json").c_str(), false);
    EXPECT_TRUE(result);
    
    // 验证交易时段
    WTSSessionInfo* trading_session = base_data_mgr->getSession("TRADING");
    ASSERT_NE(trading_session, nullptr);
    EXPECT_STREQ(trading_session->name(), "交易时段");
    EXPECT_EQ(trading_session->getOffsetMins(), 480);
    
    WTSSessionInfo* night_session = base_data_mgr->getSession("NIGHT");
    ASSERT_NE(night_session, nullptr);
    EXPECT_STREQ(night_session->name(), "夜盘时段");
    EXPECT_EQ(night_session->getOffsetMins(), 480);
}

/*!
 * \brief 测试不存在的数据查询
 */
TEST_F(WTSBaseDataMgrTest, TestNonExistentDataQuery) {
    // 加载所有配置
    ASSERT_TRUE(base_data_mgr->loadCommodities((test_dir + "/commodities.json").c_str(), false));
    ASSERT_TRUE(base_data_mgr->loadContracts((test_dir + "/contracts.json").c_str(), false));
    ASSERT_TRUE(base_data_mgr->loadSessions((test_dir + "/sessions.json").c_str(), false));
    
    // 测试不存在的合约
    EXPECT_EQ(base_data_mgr->getContract("unknown", "SHFE"), nullptr);
    EXPECT_EQ(base_data_mgr->getContract("au2412", "UNKNOWN"), nullptr);
    
    // 测试不存在的品种
    EXPECT_EQ(base_data_mgr->getCommodity("SHFE", "unknown"), nullptr);
    EXPECT_EQ(base_data_mgr->getCommodity("UNKNOWN", "au"), nullptr);
    
    // 测试不存在的交易时段
    EXPECT_EQ(base_data_mgr->getSession("UNKNOWN"), nullptr);
    
    // 测试空参数
    EXPECT_EQ(base_data_mgr->getContract("", "SHFE"), nullptr);
    // 注意：getContract("au2412", "") 会搜索所有交易所，所以应该能找到合约
    EXPECT_NE(base_data_mgr->getContract("au2412", ""), nullptr);
    EXPECT_EQ(base_data_mgr->getCommodity("", "au"), nullptr);
    EXPECT_EQ(base_data_mgr->getCommodity("SHFE", ""), nullptr);
    EXPECT_EQ(base_data_mgr->getSession(""), nullptr);
}

// ========== 错误处理测试 ==========

/*!
 * \brief 测试加载不存在的配置文件
 */
TEST_F(WTSBaseDataMgrTest, TestLoadNonExistentFiles) {
    bool result = base_data_mgr->loadCommodities("nonexistent.json", false);
    EXPECT_FALSE(result);
    
    result = base_data_mgr->loadContracts("nonexistent.json", false);
    EXPECT_FALSE(result);
    
    result = base_data_mgr->loadSessions("nonexistent.json", false);
    EXPECT_FALSE(result);
}

/*!
 * \brief 测试加载空配置文件
 */
TEST_F(WTSBaseDataMgrTest, TestLoadEmptyConfigs) {
    createEmptyConfig("empty_commodities.json");
    createEmptyConfig("empty_contracts.json");
    createEmptyConfig("empty_sessions.json");
    
    // 空配置文件应该能够加载成功，但不包含任何数据
    bool result = base_data_mgr->loadCommodities((test_dir + "/empty_commodities.json").c_str(), false);
    EXPECT_TRUE(result);
    
    result = base_data_mgr->loadContracts((test_dir + "/empty_contracts.json").c_str(), false);
    EXPECT_TRUE(result);
    
    result = base_data_mgr->loadSessions((test_dir + "/empty_sessions.json").c_str(), false);
    EXPECT_TRUE(result);
    
    // 验证没有加载任何数据
    EXPECT_EQ(base_data_mgr->getCommodity("SHFE", "au"), nullptr);
    EXPECT_EQ(base_data_mgr->getContract("au2412", "SHFE"), nullptr);
    EXPECT_EQ(base_data_mgr->getSession("TRADING"), nullptr);
}

/*!
 * \brief 测试加载无效的JSON配置文件
 */
TEST_F(WTSBaseDataMgrTest, TestLoadInvalidConfigs) {
    createInvalidConfig("invalid_commodities.json");
    createInvalidConfig("invalid_contracts.json");
    createInvalidConfig("invalid_sessions.json");
    
    bool result = base_data_mgr->loadCommodities((test_dir + "/invalid_commodities.json").c_str(), false);
    EXPECT_FALSE(result);
    
    result = base_data_mgr->loadContracts((test_dir + "/invalid_contracts.json").c_str(), false);
    EXPECT_FALSE(result);
    
    result = base_data_mgr->loadSessions((test_dir + "/invalid_sessions.json").c_str(), false);
    EXPECT_FALSE(result);
}

// ========== 数据完整性测试 ==========

/*!
 * \brief 测试合约与品种的关联关系
 */
TEST_F(WTSBaseDataMgrTest, TestContractCommodityRelation) {
    // 加载配置
    ASSERT_TRUE(base_data_mgr->loadCommodities((test_dir + "/commodities.json").c_str(), false));
    ASSERT_TRUE(base_data_mgr->loadContracts((test_dir + "/contracts.json").c_str(), false));
    
    // 获取合约信息
    WTSContractInfo* au2412 = base_data_mgr->getContract("au2412", "SHFE");
    ASSERT_NE(au2412, nullptr);
    
    // 验证合约关联的品种信息
    WTSCommodityInfo* comm_info = au2412->getCommInfo();
    ASSERT_NE(comm_info, nullptr);
    EXPECT_STREQ(comm_info->getName(), "黄金");
    EXPECT_DOUBLE_EQ(comm_info->getPriceTick(), 0.05);
    EXPECT_EQ(comm_info->getVolScale(), 1000);
}

/*!
 * \brief 测试获取所有合约列表
 */
TEST_F(WTSBaseDataMgrTest, TestGetAllContracts) {
    // 加载配置
    ASSERT_TRUE(base_data_mgr->loadCommodities((test_dir + "/commodities.json").c_str(), false));
    ASSERT_TRUE(base_data_mgr->loadContracts((test_dir + "/contracts.json").c_str(), false));
    
    // 获取所有合约
    WTSArray* contracts = base_data_mgr->getContracts();
    ASSERT_NE(contracts, nullptr);
    
    // 验证合约数量（SHFE: 3个, DCE: 1个）
    EXPECT_GE(contracts->size(), 4u);
    
    // 验证合约内容
    bool found_au2412 = false, found_au2501 = false, found_ag2412 = false, found_m2501 = false;
    
    for (uint32_t i = 0; i < contracts->size(); i++) {
        WTSContractInfo* contract = (WTSContractInfo*)contracts->at(i);
        if (contract) {
            std::string code = contract->getCode();
            if (code == "au2412") found_au2412 = true;
            else if (code == "au2501") found_au2501 = true;
            else if (code == "ag2412") found_ag2412 = true;
            else if (code == "m2501") found_m2501 = true;
        }
    }
    
    EXPECT_TRUE(found_au2412);
    EXPECT_TRUE(found_au2501);
    EXPECT_TRUE(found_ag2412);
    EXPECT_TRUE(found_m2501);
    
    contracts->release();
}

// ========== 性能测试 ==========

/*!
 * \brief 测试数据查询性能
 */
TEST_F(WTSBaseDataMgrTest, TestQueryPerformance) {
    // 加载配置
    ASSERT_TRUE(base_data_mgr->loadCommodities((test_dir + "/commodities.json").c_str(), false));
    ASSERT_TRUE(base_data_mgr->loadContracts((test_dir + "/contracts.json").c_str(), false));
    ASSERT_TRUE(base_data_mgr->loadSessions((test_dir + "/sessions.json").c_str(), false));
    
    auto start = std::chrono::high_resolution_clock::now();
    
    // 执行大量查询操作
    for (int i = 0; i < 10000; i++) {
        base_data_mgr->getContract("au2412", "SHFE");
        base_data_mgr->getCommodity("SHFE", "au");
        base_data_mgr->getSession("TRADING");
        base_data_mgr->getContract("m2501", "DCE");
        base_data_mgr->getCommodity("DCE", "m");
    }
    
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    std::cout << "基础数据查询性能测试: 50000次查询耗时 " << duration.count() << "ms" << std::endl;
    
    // 性能要求：50000次查询应该在50ms内完成
    EXPECT_LT(duration.count(), 50);
}

// ========== 多线程安全性测试 ==========

/*!
 * \brief 测试多线程并发查询安全性
 */
TEST_F(WTSBaseDataMgrTest, TestConcurrentQueries) {
    // 加载配置
    ASSERT_TRUE(base_data_mgr->loadCommodities((test_dir + "/commodities.json").c_str(), false));
    ASSERT_TRUE(base_data_mgr->loadContracts((test_dir + "/contracts.json").c_str(), false));
    ASSERT_TRUE(base_data_mgr->loadSessions((test_dir + "/sessions.json").c_str(), false));
    
    std::atomic<int> success_count(0);
    std::atomic<int> error_count(0);
    
    // 创建多个线程并发查询
    std::vector<std::thread> threads;
    for (int i = 0; i < 4; i++) {
        threads.emplace_back([&]() {
            for (int j = 0; j < 1000; j++) {
                try {
                    WTSContractInfo* contract = base_data_mgr->getContract("au2412", "SHFE");
                    WTSCommodityInfo* commodity = base_data_mgr->getCommodity("SHFE", "au");
                    WTSSessionInfo* session = base_data_mgr->getSession("TRADING");
                    
                    if (contract && commodity && session) {
                        success_count++;
                    } else {
                        error_count++;
                    }
                } catch (...) {
                    error_count++;
                }
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }
    
    std::cout << "多线程测试结果: 成功 " << success_count.load() 
              << " 次, 错误 " << error_count.load() << " 次" << std::endl;
    
    // 验证没有发生错误
    EXPECT_EQ(error_count.load(), 0);
    EXPECT_EQ(success_count.load(), 4000);
}

// ========== 边界条件测试 ==========

/*!
 * \brief 测试大量数据处理
 */
TEST_F(WTSBaseDataMgrTest, TestLargeDataSet) {
    // 创建包含大量数据的配置文件
    std::ofstream comm_file(test_dir + "/large_commodities.json");
    comm_file << "{\n";
    
    const char* exchanges[] = {"SHFE", "DCE", "CZCE", "CFFEX", "INE"};
    const char* commodities[] = {"au", "ag", "cu", "al", "zn", "pb", "ni", "sn", "ss", "rb"};
    
    for (int i = 0; i < 5; i++) {
        if (i > 0) comm_file << ",\n";
        comm_file << "\"" << exchanges[i] << "\": {\n";
        
        for (int j = 0; j < 10; j++) {
            if (j > 0) comm_file << ",\n";
            comm_file << "\"" << commodities[j] << "\": {\n";
            comm_file << "\"name\": \"" << commodities[j] << "品种\",\n";
            comm_file << "\"pricetick\": 1,\n";
            comm_file << "\"volscale\": 10,\n";
            comm_file << "\"category\": 0,\n";
            comm_file << "\"covermode\": 0,\n";
            comm_file << "\"pricemode\": 0,\n";
            comm_file << "\"trademode\": 2,\n";
            comm_file << "\"lotstick\": 1,\n";
            comm_file << "\"minlots\": 1,\n";
            comm_file << "\"session\": \"TRADING\"\n";
            comm_file << "}";
        }
        comm_file << "\n}";
    }
    comm_file << "\n}";
    comm_file.close();
    
    // 加载大数据集
    bool result = base_data_mgr->loadCommodities((test_dir + "/large_commodities.json").c_str(), false);
    EXPECT_TRUE(result);
    
    // 验证部分数据
    EXPECT_NE(base_data_mgr->getCommodity("SHFE", "au"), nullptr);
    EXPECT_NE(base_data_mgr->getCommodity("DCE", "cu"), nullptr);
    EXPECT_NE(base_data_mgr->getCommodity("CZCE", "ag"), nullptr);
}

// ========== 内存管理测试 ==========

/*!
 * \brief 测试重复加载配置的内存管理
 */
TEST_F(WTSBaseDataMgrTest, TestRepeatedLoading) {
    // 重复加载配置文件多次
    for (int i = 0; i < 5; i++) {
        bool result = base_data_mgr->loadCommodities((test_dir + "/commodities.json").c_str(), false);
        EXPECT_TRUE(result);
        
        result = base_data_mgr->loadContracts((test_dir + "/contracts.json").c_str(), false);
        EXPECT_TRUE(result);
        
        result = base_data_mgr->loadSessions((test_dir + "/sessions.json").c_str(), false);
        EXPECT_TRUE(result);
        
        // 验证数据仍然正确
        EXPECT_NE(base_data_mgr->getCommodity("SHFE", "au"), nullptr);
        EXPECT_NE(base_data_mgr->getContract("au2412", "SHFE"), nullptr);
        EXPECT_NE(base_data_mgr->getSession("TRADING"), nullptr);
    }
}

// ========== 综合功能测试 ==========

/*!
 * \brief 测试完整的基础数据管理流程
 */
TEST_F(WTSBaseDataMgrTest, TestCompleteWorkflow) {
    // 1. 加载所有配置文件
    ASSERT_TRUE(base_data_mgr->loadSessions((test_dir + "/sessions.json").c_str(), false));
    ASSERT_TRUE(base_data_mgr->loadCommodities((test_dir + "/commodities.json").c_str(), false));
    ASSERT_TRUE(base_data_mgr->loadContracts((test_dir + "/contracts.json").c_str(), false));
    
    // 2. 验证数据完整性
    WTSContractInfo* au2412 = base_data_mgr->getContract("au2412", "SHFE");
    ASSERT_NE(au2412, nullptr);
    
    WTSCommodityInfo* au_comm = au2412->getCommInfo();
    ASSERT_NE(au_comm, nullptr);
    EXPECT_STREQ(au_comm->getName(), "黄金");
    
    WTSSessionInfo* session = au_comm->getSessionInfo();
    ASSERT_NE(session, nullptr);
    EXPECT_STREQ(session->name(), "交易时段");
    
    // 3. 验证所有交易所的数据
    const char* exchanges[] = {"SHFE", "DCE"};
    const char* shfe_products[] = {"au", "ag"};
    const char* dce_products[] = {"m"};
    
    // 验证SHFE
    for (const char* product : shfe_products) {
        WTSCommodityInfo* comm = base_data_mgr->getCommodity("SHFE", product);
        EXPECT_NE(comm, nullptr);
        if (comm) {
            EXPECT_FALSE(std::string(comm->getName()).empty());
        }
    }
    
    // 验证DCE
    for (const char* product : dce_products) {
        WTSCommodityInfo* comm = base_data_mgr->getCommodity("DCE", product);
        EXPECT_NE(comm, nullptr);
        if (comm) {
            EXPECT_FALSE(std::string(comm->getName()).empty());
        }
    }
    
    // 4. 验证合约数据
    WTSArray* all_contracts = base_data_mgr->getContracts();
    ASSERT_NE(all_contracts, nullptr);
    EXPECT_GT(all_contracts->size(), 0u);
    all_contracts->release();
} 